<?php
class YWSReflector 
{
	private $_default = "_DEFAULT_";
	private $_restrict_methods = array("actions");
    private $_restrict_modules = array("gii");
    
    public function run()
    {
        $r = new YWSReflector();
        $r->synchronize();
        $modules = $this->getModules();
        foreach ($modules as $module)
        {
            $r->synchronize($module);
        }
    }
    
	public function synchronize($module = null) 
	{
		// Get list of all controllers
		$list = array();
		// Load all controllers into the system
		$this->loadAllControllers($module);
        
        if ($module == null)
        {
            $controllers = $this->getDefaultControllers();
        }
        else
        {
            $controllers = $this->getModuleControllers($module);
        }
        for ($i = 0; $i < count($controllers); $i++)
        {
            $list[] = $controllers[$i];
        }
		
		// Synchronisation process
        foreach($list as $item)
        {
            $parts = explode(".", $item);
            // Check if page exists
            $finder = PortalPages::model()->find("namespace = '".$item."'");
            if ($finder == null)
            {
                // Insert new page
                $entity = new PortalPages;
                $entity->module = $parts[0];
                $entity->controller = $parts[1];
                $entity->action = $parts[2];
                $entity->namespace = $item;
                $entity->save();
                $entity->refresh();
                $entity = null;
            }
            
            // Delete the missing physical file
            $list = PortalPages::model()->findAll();
            foreach ($list as $item)
            {
                $parts = explode(".", $item->namespace);
                // Check if file exists
                if ($parts[0] == $this->_default)
                    $path = Yii::app()->basePath."/controllers/".$parts[1]."Controller.php";
                else
                    $path = Yii::app()->basePath."/modules/".$parts[0]."/controllers/".$parts[1]."Controller.php";

                if (!file_exists($path))
                {
                    echo "Deleting item: ".$item->namespace."<br />";
                    $item->delete();
                }
            }
            
            
        }
	}
	
	public function getDefaultControllers()
	{
		$list = array();
		$path = Yii::app()->basePath."/controllers";
		$dir = opendir($path);
		while (($file = readdir($dir)) !== false) 
		{
			if ($file[0] != ".")
			{
				// The sample $file such as HomeController.php
				// Strip the .php to get controller name
				$controller = substr($file, 0, strlen($file) - 4);
				// Start reflection process
                try
                {
				$reflector = new ReflectionClass($controller);
                }
                catch(Exception $e)
                {
                    throw new Exception($e->getMessage());
                }
				$methods = $reflector->getMethods();
				foreach ($methods as $method)
				{
					// Raw name such as actionIndex
					$raw = $method->getName();
					if (substr($raw, 0, 6) === "action" && !in_array($raw, $this->_restrict_methods))
					{
						// Get rid of "action"
						$name = substr($raw, 6, strlen($raw) - 1);
                        $ctr = substr($controller, 0, strlen($controller) - 10);
						$namespace = implode(".", array($this->_default, $ctr, $name));
						// Add to list
						$list[] = $namespace;
					}
				}
			}
		}
		return $list;
	}
	
	public function getModuleControllers($module_name)
	{
		$list = array();
		$path = Yii::app()->basePath."/modules/".$module_name."/controllers";
		$dir = opendir($path);
		while (($file = readdir($dir)) !== false) 
		{
			if ($file[0] != ".")
			{
				// The sample $file such as HomeController.php
				// Strip the .php to get controller name
				$controller = substr($file, 0, strlen($file) - 4);
				// Start reflection process
				try
                {
				$reflector = new ReflectionClass($controller);
                }
                catch(Exception $e)
                {
                    throw new Exception($e->getMessage());
                }
                
				$methods = $reflector->getMethods();
				foreach ($methods as $method)
				{
					// Raw name such as actionIndex
					$raw = $method->getName();
					if (substr($raw, 0, 6) === "action" && !in_array($raw, $this->_restrict_methods))
					{
						// Get rid of "action"
						$name = substr($raw, 6, strlen($raw) - 1);
                        $ctr = substr($controller, 0, strlen($controller) - 10);
						$namespace = implode(".", array($module_name, $ctr, $name));
						// Add to list
						$list[] = $namespace;
					}
				}
			}
		}
		return $list;
	}
	
	public function getModules()
	{
		$yii_modules = Yii::app()->getModules();
        $module_list = array();
        foreach($yii_modules as $key=>$value)
        {
            if (!in_array($key, $this->_restrict_modules))
                    $module_list[] = $key;
        }
		return $module_list;
	}
	
	public function loadAllControllers($module = null)
	{
        if ($module == null)
        {
            // Load Default controllers
            foreach (glob(Yii::getPathOfAlias('application.controllers') . "/*Controller.php") as $controller)
            {
                $class = basename($controller, ".php");
                Yii::import("application.controllers." . $class, true);
            }
        }
        else
        {
            // Get Module List
            $modules = $this->getModules();

            foreach ($modules as $module)
            {
                // Load module controllers
                foreach (glob(Yii::getPathOfAlias('application.modules.'.$module.'.controllers') . "/*Controller.php") as $controller)
                {
                    $class = basename($controller, ".php");
                    Yii::import("application.modules.".$module.".controllers." . $class, true);
                }
            }
        }
	}
}